使用!!操作符转换布尔值

有时候我们需要对一个变量查检其是否存在或者检查其值是否有一个有效值,如果存在就返回true值。可以使用!!前缀做检测,只要变量的值为:0null""undefined或者NaN都将返回的是false,反之返回的是true。如下:

1
2
3
4
5
6
7
8
9
10
11
12
var temp = "this is awsome!";
console.log(temp); // this is awsome
console.log(!!temp); // true
var temp = 0;
console.log(temp); // 0
console.log(!!temp); // false
var temp = "";
console.log(temp); // ""
console.log(!!temp); // false
...

当然,! 操作符也可以进行上述转换,不过它恰好会得到相反的布尔值。

使用+将字符串转换成数字

这个技巧适合用于数字形式的字符串 or 布尔值转数字,否则将返回 NaN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var temp = "112";
console.log(temp); // 112
console.log(typeof(temp)); // string
console.log(+temp); // 112
console.log(typeof(+temp)); // number
var temp = "asdf";
console.log(+temp);//NaN
var temp = false;
console.log(+temp);//0
var temp = true;
console.log(+temp);//1

也适用于Date,它将返回的是时间戳数字:

1
2
console.log(new Date()) // Sat May 21 2016 21:24:41 GMT+0800 (CST)
console.log(+new Date()) // 1463837110400

&& 条件符

如果你有一段这样的代码:

1
2
3
if (isReady) {
login();
}

可以简写成这样:

isReady && login();

你也可以这样检测一些属性或函数是否存在于一个对象中,如下:

user && user.name 或者 user && user.login();

这个技巧在实际项目中十分常见,它可以有效防止后端接口异常时,返回的数据对象结构变化,或属性 or 方法置空 or 改变导致程序报错终止。

使用||运算符

在 ES6 中有默认参数这一特性。为了在旧的浏览器中模拟这一特性,可以使用||操作符,并且将默认值当做第二个参数传入。如果第一个参数返回的值为false,那么第二个值将会认为是一个默认值。如下:

1
2
3
4
5
6
7
var fullname; //未初始化 null
var temp = fullname || "Oliver Queen";
console.log(temp); // Oliver Queen
var fullname = "elevenbeans"
var temp = fullname || "Oliver Queen";
console.log(temp); // elevenbeans

优先使用===,而不是==

==(或!=)操作符在需要的时候会自动执行类型转换。===(或!==)操作不会执行任何转换。它将比较值和类型,而且在速度上也被认为优于==

所以,在类型相同的情况下比较两个值是否相同,优先使用===

能使用 switch/case 语句优先用,否则考虑 if/else

在循环中缓存 array.length

在处理一个数组循环时,如果每一次都array.length去判断大小,代码的性能是非常不好的

如果是一个小型数组,这样做还不会有多大影响,如果你要处理的是一个大的数组,这将会导致一些延误。

为了避免这种现象出现,可以将array.length做一个缓存:

1
2
3
4
5
6
7
8
9
10
// bad case
for(var i = 0; i < array.length; i++) {
console.log(array[i]);
}
//good case
var length = array.length;
for(var i = 0; i < length; i++) {
console.log(array[i]);
}

检测对象中属性

当你需要检测一些属性是否存在,避免运行未定义的函数或属性时,这个小技巧就显得很有用。例如,你想使用document.querySelector()来选择一个id,并且让它能兼容 IE6 浏览器,就可以使用如下代码:

1
2
3
4
5
if ('querySelector' in document) {
document.querySelector("#id");
} else {
document.getElementById("id");
}

在这个示例中,如果document不存在querySelector函数,那么就会调用docuemnt.getElementById("id")

类似得,前文提到的并条件符 &&,也可解决这个问题:

1
2
3
4
5
if (document && document.querySelector) {
document.querySelector("#id");
} else {
document.getElementById("id");
}

获取数组中最后一个元素

Array.prototype.slice(begin,end)用来获取 begin 和 end 之间的数组元素。如果你不设置end 参数,将会将数组的默认长度值当作 end 值。如果你设置一个负值作为 begin 的值,那么你可以获取数组的最后 N 个元素。如:

1
2
3
4
var array = [1,2,3,4,5,6];
console.log(array.slice(-1)); // [6]
console.log(array.slice(-2)); // [5,6]
console.log(array.slice(-3)); // [4,5,6]

数组截断

通过array.length = n来截断数组,这个小技巧主要用来锁定数组的大小,如果用于删除数组中的一些元素来说,是非常有用的。如下:

1
2
3
4
5
var array = [1,2,3,4,5,6];
console.log(array.length); // 6
array.length = 3;
console.log(array.length); // 3
console.log(array); // [1,2,3]

合并数组

如果你要合并两个数组,一般情况之下你都会使用Array.concat()函数:

1
2
3
var array1 = [1,2,3];
var array2 = [4,5,6];
console.log(array1.concat(array2)); // [1,2,3,4,5,6];

然后这个函数并不适合用来合并两个大型的数组,因为其将消耗大量的内存来存储新创建的数组。在这种情况之个,可以使用Array.push().apply(arr1,arr2)来替代创建一个新数组。这种方法不是用来创建一个新的数组,其只是将第一个第二个数组合并在一起,同时减少内存的使用:

1
2
3
var array1 = [1,2,3];
var array2 = [4,5,6];
console.log(array1.push.apply(array1, array2)); // [1,2,3,4,5,6];

将 DomNodeList 转换成数组

如果你运行document.querySelectorAll(“p”)函数时,它可能返回 DOM 元素的数组,也就是NodeList 对象。但这个对象不具有数组的函数功能,比如sort()reduce()map()filter()等。为了让这些原生的数组函数功能也能用于其上面,需要将节点列表转换成数组。可以使用[].slice.call(elements)来实现:

1
2
3
var elements = document.querySelectorAll("p"); // NodeList
var arrayElements = [].slice.call(elements); // Now the NodeList is an array
var arrayElements = Array.from(elements); // This is another way of converting NodeList to Array

数组元素的洗牌

对于数组元素的洗牌,不需要使用任何外部的库,比如 Lodash,只要这样做:

1
2
var list = [1,2,3,4,5,6];
console.log(list.sort(function() { return Math.random() - 0.5 })); // [2,1,3,5,4,6]

各种随机相关:

从数组中获取一个随机

1
2
var items = [12, 548 , '&#039;a&#039;' , 2 , 5478 , '&#039;', 'foo&#039;' , 8852, '&#039;', 'Doe&#039;' , 2145 , 119];
var randomItem = items[Math.floor(Math.random() * items.length)];

在特定范围内获取一个随机数
var x = Math.floor(Math.random() * (max - min + 1)) + min;

在0和设定的最大值之间生成一个数字数组

1
2
var numbersArray = [] , max = 100;
for( var i=1; numbersArray.push(i++) &lt; max;); // numbers = [0,1,2,3 ... 100]

生成一个随机的数字字母字符串

1
2
3
4
5
function generateRandomAlphaNum(len) {
var rdmstring = &quot;&quot;;
for( ; rdmString.length &amp;lt; len; rdmString += Math.random().toString(36).substr(2));
return rdmString.substr(0, len);
}

使用 map() 方法来遍历一个数组里的项

1
2
3
4
var squares = [1,2,3,4].map(function (val) {
return val * val;
});
// squares will be equal to [1, 4, 9, 16]

基于JSON的序列化和反序列化(serialization and deserialization)

1
2
3
4
5
var person = {name :&#039;Saad&#039;, age : 26, department : {ID : 15, name : &quot;R&amp;D&quot;} };
var stringFromPerson = JSON.stringify(person);
/* stringFromPerson is equal to &quot;{&quot;name&quot;:&quot;Saad&quot;,&quot;age&quot;:26,&quot;department&quot;:{&quot;ID&quot;:15,&quot;name&quot;:&quot;R&amp;D&quot;}}&quot; */
var personFromString = JSON.parse(stringFromPerson);
/* personFromString is equal to person object */

自调用的匿名函数

这个经常被称为自调用匿名函数(Self-Invoked Anonymous Function)或者即时调用函数表达式(IIFE-Immediately Invoked Function Expression)。这是一个在创建后立即自动执行的函数,通常如下:

1
2
3
4
5
6
7
(function(){
// some private code that will be executed automatically
})();
(function(a,b){
var result = a+b;
return result;
})(10,20)

作用:

Javascript 中没用块级作用域的概念,如果在多人开发的项目上,你在全局或局部作用域中声明了一些变量,可能会被其他人不小心用同名的变量给覆盖掉,产生严重的冲突。

根据 Javascript 函数作用域链的特性,可以使用这种技术可以模仿一个私有作用域,用匿名函数作为一个“容器”,“容器”内部可以访问外部的变量,而外部环境不能访问“容器”内部的变量,所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,俗称“匿名包裹器”或“命名空间”。
著名的 JS 库 JQuery 使用的就是这种方法,将JQuery代码包裹在( function (window,undefined){…jquery代码…} (window)中,在全局作用域中调用 JQuery 代码时,可以达到保护 JQuery 内部变量的作用。

Reference: